﻿using System;
using System.Globalization;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Xml.Serialization;
using DACU.Player.Enums;
using DACU.Tools.JavaScript;
using DACU.VkontakteApi.Collections;

namespace DACU.Tools
{
	class Utils
	{
		private static readonly char[] SEntityEndingChars;
 
		static Utils()
		{
			SEntityEndingChars = new[] { ';', '&' };
		}

		public static string Md5Hash(string instr)
		{
			var strHash = new StringBuilder();
			byte[] hash = new MD5CryptoServiceProvider().ComputeHash(Encoding.Default.GetBytes(instr));
			foreach (byte b in hash)
				strHash.Append(b.ToString("x2"));
			return strHash.ToString();
		}

		public static object JsonToData(string json)
		{
			var js = new JavaScriptSerializer();
			return js.DeserializeObject(json);
		}

		public static string ObjectToJson(object data)
		{
			var js = new JavaScriptSerializer();
			return js.Serialize(data);
		}

		internal static string UrlDecode(string value)
		{
			return UrlDecode(value, Encoding.UTF8);
		}

		public static string Get_sig(string userId, VKParametrCollection param, string secret)
		{
			// example "100172api_id=1854119fields=photo,sexformat=JSONmethod=getProfilesuids=100172v=3.0655df68ded"
			return Md5Hash(userId + param.ToFormatedString() + secret);
		}

		internal static string UrlDecode(string value, Encoding encoding)
		{
			if (value == null)
				return null;
			int length = value.Length;
			var decoder = new UrlDecoder(length, encoding);
			for (int i = 0; i < length; i++)
			{
				char ch = value[i];
				if (ch == '+')
					ch = ' ';
				else
					if ((ch == '%') && (i < (length - 2)))
					{
						if ((value[i + 1] == 'u') && (i < (length - 5)))
						{
							int num3 = HexToInt(value[i + 2]);
							int num4 = HexToInt(value[i + 3]);
							int num5 = HexToInt(value[i + 4]);
							int num6 = HexToInt(value[i + 5]);
							if (((num3 < 0) || (num4 < 0)) || ((num5 < 0) || (num6 < 0)))
								goto Label_010B;
							ch = (char) ((((num3 << 12) | (num4 << 8)) | (num5 << 4)) | num6);
							i += 5;
							decoder.AddChar(ch);
							continue;
						}
						int num7 = HexToInt(value[i + 1]);
						int num8 = HexToInt(value[i + 2]);
						if ((num7 >= 0) && (num8 >= 0))
						{
							var b = (byte) ((num7 << 4) | num8);
							i += 2;
							decoder.AddByte(b);
							continue;
						}
					}
			Label_010B:
				if ((ch & 0xff80) == 0)
					decoder.AddByte((byte) ch);
				else
					decoder.AddChar(ch);
			}
			return decoder.GetString();
		}

		public static string HtmlDecode(string s)
		{
			if (s == null)
				return null;
			if (s.IndexOf('&') < 0)
				return s;
			var sb = new StringBuilder();
			var output = new StringWriter(sb);
			HtmlDecode(s, output);
			return sb.ToString();
		}

		public static void HtmlDecode(string s, TextWriter output)
		{
			if (s != null)
			{
				if (s.IndexOf('&') < 0)
					output.Write(s);
				else
				{
					int length = s.Length;
					for (int i = 0; i < length; i++)
					{
						char ch = s[i];
						if (ch == '&')
						{
							int num3 = s.IndexOfAny(SEntityEndingChars, i + 1);
							if ((num3 > 0) && (s[num3] == ';'))
							{
								string entity = s.Substring(i + 1, (num3 - i) - 1);
								if ((entity.Length > 1) && (entity[0] == '#'))
								{
									try
									{
										ch = (entity[1] == 'x') || (entity[1] == 'X')
										     	? (char) int.Parse(entity.Substring(2), NumberStyles.AllowHexSpecifier)
										     	: (char) int.Parse(entity.Substring(1));
										i = num3;
									}
									catch (FormatException)
									{
										i++;
									}
									catch (ArgumentException)
									{
										i++;
									}
								}
								else
								{
									i = num3;
									char ch2 = HtmlEntities.Lookup(entity);
									if (ch2 != '\0')
										ch = ch2;
									else
									{
										output.Write('&');
										output.Write(entity);
										output.Write(';');
										goto Label_0103;
									}
								}
							}
						}
						output.Write(ch);
						Label_0103:
						;
					}
				}
			}
		}

		public static int HexToInt(char h)
		{
			if ((h >= '0') && (h <= '9'))
				return (h - '0');
			if ((h >= 'a') && (h <= 'f'))
				return ((h - 'a') + 10);
			if ((h >= 'A') && (h <= 'F'))
				return ((h - 'A') + 10);
			return -1;
		}

		public static bool IsKnownFormat(string extension)
		{
			if(extension==null) return false;
			extension = extension.ToLower();
			extension = extension.Trim(new[] {'.'});
			string[] names = Enum.GetNames(typeof(SupportedFormats));
			var sb = new StringBuilder();
			for (int i = 0; i < names.Length; i++)
				sb.AppendFormat("{0}|", names[i]);
			sb.Replace("All|", "");
			sb.Replace("None|", "");
			return sb.ToString().IndexOf(extension) > 0;
		}
	}
}
